'''
Module to hold Insert Component dialog.

Author: Esben Bugge, 2009.
'''

import wx

from plugins.builder import *

class InsertComponentDialog(wx.Panel):
    '''
    Class for displaying the Insert Component dialog.
    '''
    def OnSetFocus(self, evt):
        evt.Skip()

    def OnKillFocus(self, evt):
        evt.Skip()

    def __init__(self, parent, data, pluginman, componentLib):
        
        self.pluginman = pluginman
        
        # whether the user have downloaded components from server
        #self.downloadMade = False
        self.componentLib = componentLib
        
        self.dialog = wx.Dialog(parent, -1, "Insert Component", style = wx.DEFAULT_FRAME_STYLE | wx.WANTS_CHARS)
        wx.Panel.__init__(self, self.dialog, -1)
        
        # sizers to organize layout
        gridSizer = wx.FlexGridSizer(cols=3)
        upLeft = wx.BoxSizer(wx.VERTICAL)
        up = wx.BoxSizer(wx.VERTICAL)
        upRight = wx.BoxSizer(wx.VERTICAL)
        left = wx.BoxSizer(wx.VERTICAL)
        right = wx.BoxSizer(wx.VERTICAL)
        downLeft = wx.BoxSizer(wx.VERTICAL)
        down = wx.BoxSizer(wx.VERTICAL)
        downRight = wx.BoxSizer(wx.VERTICAL)
        center = wx.BoxSizer(wx.VERTICAL) # will hold the main insert-functionality
        gridSizer.Add(upLeft)
        gridSizer.Add(up)
        gridSizer.Add(upRight)
        gridSizer.Add(left)
        gridSizer.Add(center)
        gridSizer.Add(right)
        gridSizer.Add(downLeft)
        gridSizer.Add(down)
        gridSizer.Add(downRight)
        
        # add areas from plugins
        self.pluginman.drawInsertCompArea(location_INSERTCOMP_TOP,up,self)
        self.pluginman.drawInsertCompArea(location_INSERTCOMP_BOTTOM,down,self) # not used anywhere yet
        self.pluginman.drawInsertCompArea(location_INSERTCOMP_LEFT,left,self) # not used anywhere yet
        self.pluginman.drawInsertCompArea(location_INSERTCOMP_RIGHT,right,self) # not used anywhere yet        

        # local data
        self.data = data
        print 'self.data:', self.data
        #self.plugin_ctrls = {}
        self.package_list = []
        for package in self.data.keys():
            self.package_list.append(package)
        self.package_list.sort() 
        
        componentList= self.data[self.package_list[0]].keys()
        componentList.sort()
        self.selectedPackage = self.package_list[0]
        self.selectedComponent = self.data[self.package_list[0]].keys()[0]
        
        # Non-plugin area: center
        row1 = wx.BoxSizer(wx.HORIZONTAL)
        row2 = wx.BoxSizer(wx.HORIZONTAL)
        row3 = wx.BoxSizer(wx.HORIZONTAL)
        row4 = wx.BoxSizer(wx.HORIZONTAL)
        #row5 = wx.BoxSizer(wx.HORIZONTAL)
        center.Add(row1)
        center.Add(row2)
        center.Add(row3)
        center.Add(row4)
        #center.Add(row5)
        
        # row 1: header
        row1.Add(wx.StaticText(self, -1, "Select a component from a package to insert."),flag=wx.ALL,border=10)
        
        # row 2: package selector and new-button
        row2.Add(wx.StaticText(self, -1, "Package:"),flag=wx.LEFT|wx.TOP|wx.BOTTOM,border=10)
        self.cb = wx.ComboBox(self, -1, self.package_list[0], choices=self.package_list, style=wx.CB_READONLY)
        row2.Add(self.cb, flag=wx.ALL, border=10)
        self.btnNew = wx.Button(self, wx.ID_NEW, "Create new ...")
        row2.Add(self.btnNew,flag=wx.ALL, border=10)
        self.Bind(wx.EVT_BUTTON, self.EvtNewButton, self.btnNew)
        self.Bind(wx.EVT_COMBOBOX, self.EvtLclPackBox, self.cb)
        self.Bind(wx.EVT_TEXT, self.EvtText, self.cb)
        self.Bind(wx.EVT_TEXT_ENTER, self.EvtTextEnter, self.cb)
        self.cb.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
        self.cb.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
        
        # row 3: component list and profile-text
        self.lb = wx.ListBox(self, -1, size=(250,300), choices=componentList, style=wx.LB_SINGLE)
        row3.Add(self.lb,flag=wx.ALL,border=10)
        self.Bind(wx.EVT_LISTBOX, self.EvtLclListBox, self.lb)
        self.Bind(wx.EVT_LISTBOX_DCLICK, self.EvtLclListBox_Dclick, self.lb)
        self.info = wx.StaticText(self, -1, "",size=(200,200))
        row3.Add(self.info,flag=wx.ALL,border=10)
        
        # row 4: insert button and version selector
        self.versionCb = wx.ComboBox(self, -1, '3', choices=[], style=wx.CB_READONLY)
        self.Bind(wx.EVT_COMBOBOX, self.EvtVersionCb, self.versionCb)
        self.versionCb.Disable()
        row4.Add(wx.StaticText(self, -1, "Version:"),flag=wx.LEFT|wx.TOP|wx.BOTTOM|wx.ALIGN_LEFT,border=10)
        row4.Add(self.versionCb, flag=wx.ALL|wx.ALIGN_LEFT, border=10)
        self.btnOK = wx.Button(self, wx.ID_OK, "Insert")
        self.btnCancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
        self.btnOK.Disable()
        row4.Add(self.btnOK,flag=wx.ALL|wx.ALIGN_RIGHT,border=10)
        row4.Add(self.btnCancel,flag=wx.ALL|wx.ALIGN_RIGHT,border=10)
        
        # row 5: info area
        #compInfo = wx.StaticText(self, -1, 'Version: All\nCollaborators:Anders, Brian, Christian, Daniel\nComment on version: This is a good version\nYour permissions: read-only',size=(200,100))
        #row5.Add(wx.StaticText(self, -1, "Component info: COMPNAME"),flag=wx.ALL,border=10)
        #row5.Add(compInfo,flag=wx.ALL,border=10)
        
        self.SetAutoLayout(True)
        self.SetSizer(gridSizer)
        gridSizer.SetSizeHints(self.dialog)
        
        # Fix: makes windows redraw the dialog
        #self.dialog.SetClientSize(wx.Size(850,600))
        
    def EvtNewButton(self, evt):
       self.dialog.EndModal(wx.ID_NEW)
       
    def _GetComponentProfile(self,component,package):
        '''
        Returns a string with the profile description
        of the given component in the given package. The
        string is formatted to fit in a info-box of static
        text.
        @param component:
        @param package:
        '''
        if (component != ''):
            cObj = self.data[package][component]
            print cObj

            t= 'Component profile: ' + component + '\n\nInputs ('+str(len(cObj.inputs))+'):\n'
            for x in cObj.inputs:
                t = t + x[0] + ' <- [' + str(x[1]) + ']\n'
            t = t + '\nOutputs ('+str(len(cObj.outputs))+'):\n'
            for x in cObj.outputs:
                t = t + x[0] + ' -> [' + str(x[1]) + ']\n'

            self.pluginman.drawComponentInfo(self, cObj)
        else:
            t = ''
        return t
    
       
    # When the user selects a package, we go here.
    def EvtLclPackBox(self, evt):
        self.selectedPackage = evt.GetString()
        componentList= self.data[self.selectedPackage].keys()
        componentList.sort()
        self.lb.Set(componentList)
        
    # if needed this should add a component to the list of local components
    def AddComponent(self, package, name, component,compPath):
        print 'Adding ' + name + ' to ' + package + ' with object: ' + str(component) + ' to list of local components'
        cObj = self.componentLib.addComponent(component['csp']['1'],compPath)
        
        if not self.data.has_key(package):
            self.data[package] = {}
        self.data[package][name] = cObj
        
        self.package_list = []
        for package in self.data.keys():
            self.package_list.append(package)
        self.package_list.sort() 
        
        componentList= self.data[self.package_list[0]].keys()
        componentList.sort()
        self.selectedPackage = self.package_list[0]
        self.selectedComponent = self.data[self.package_list[0]].keys()[0]
        
        self.lb.Set(componentList)
        self.cb.SetItems(self.package_list)
        self.cb.SetStringSelection(self.package_list[0])

    def GetSelection(self):
        return self.selectedComponent
    
    def GetVersion(self):
        return self.selectedVersion
        
    def EvtVersionCb(self, evt):
        self.selectedVersion = evt.GetString()

    def EvtLclListBox(self, evt):
        '''
        Event when a local component is selected.
        @param evt:
        '''
        self.selectedComponent = evt.GetString()

        if (self.selectedComponent != ''):

            # get versions to show in version checkbox
            cObj = self.data[self.selectedPackage][self.selectedComponent]
            versions = cObj.getVersions()
            versions.sort(reverse=True)
            self.versionCb.SetItems(versions)
            self.versionCb.SetSelection(0)
            self.selectedVersion = versions[0]

            self.btnOK.Enable()
            self.versionCb.Enable()
        t = self._GetComponentProfile(self.selectedComponent, self.selectedPackage)
        
        self.info.SetLabel(t)
        
        
    def EvtLclListBox_Dclick(self, evt):
        self.dialog.EndModal(wx.ID_OK)
    
    # Capture events every time a user hits a key in the text entry field.
    def EvtText(self, evt):
        evt.Skip()

    # Capture events when the user types something into the control then
    # hits ENTER.
    def EvtTextEnter(self, evt):
        evt.Skip()

    def ShowModal(self):
        return self.dialog.ShowModal()
        
    def Destroy(self):
        self.dialog.Destroy()